import requests
import json
import base64
import hmac
import hashlib
import time
import os
from urllib.parse import urlencode
from ..exceptions import PlatformAPIException, PlatformRequestException, PlatformNotSupportSymbolException, PlatformClientException
from ..restapibase import RestAPIBase
from Platforms.key import ACCOUNT_ID
from .symbols import symbols


class BitstampRESTAPI(RestAPIBase):
    """docstring for BitfinexRESTAPI"""

    def __init__(self, api_key, secret_key, isdebug=False):
        self.api_key = api_key
        self.api_secret = secret_key
        self.isdebug = isdebug
        self.url = 'https://www.bitstamp.net'

    def _debug(self, result):
        if self.isdebug:
            print(result)

    def _get_auth(self, data):

        data['key'] = self.api_key
        nonce = int(time.time())
        msg = str(nonce) + ACCOUNT_ID["bitstamp"] + self.api_key

        signature = hmac.new(
            self.api_secret.encode('utf-8'), msg=msg.encode('utf-8'),
            digestmod=hashlib.sha256).hexdigest().upper()
        data['signature'] = signature
        data['nonce'] = nonce
        return data

    def _get(self, endpoint, params={}):
        url = self.url + endpoint
        self._debug(url)

        response = requests.get(url, params=params)
        rescode = response.status_code

        self._debug(response.text)

        errmsg = 'StatusCode: GET %s \nURL:%s \nParams: %s \nResponse: %s' % (
            response.status_code, url, str(params), response.text)
        response = response.json()

        if response or rescode == 200:
            if isinstance(response, dict) and 'reson' in response.keys():
                raise PlatformAPIException(errmsg)
            else:
                return response
        else:
            raise PlatformRequestException(errmsg)

    def _post(self, endpoint, data={}):
        url = self.url + endpoint
        self._debug(url)

        auth_data = self._get_auth(data)
        response = requests.post(url, data=auth_data)
        rescode = response.status_code

        self._debug(response.text)

        errmsg = 'StatusCode: POST %s \nURL:%s \nData: %s \nResponse: %s' % (
            response.status_code, url, str(data), response.text)
        response = response.json()

        if response or rescode == 200:
            if isinstance(response, dict) and 'reson' in response.keys():
                raise PlatformAPIException(errmsg)
            else:
                return response
        else:
            raise PlatformRequestException(errmsg)

    # EndPoints
    def _symbols(self):
        url = '/api/v2/trading-pairs-info/'
        resjson = self._get(url)
        self._debug('symbols: \n' + json.dumps(resjson, indent=2))

        result = []

        for res in resjson:
            result.append(res["url_symbol"])
        sw = open(os.path.dirname(
            os.path.realpath(__file__)) + '/symbols.py', 'w')
        sw.write('symbols = ' + str(result))
        sw.close()

        self._debug('symbols: \n' + json.dumps(result, indent=2))
        return result

    # Public
    def get_currency(self, currency):
        return currency.lower()

    def get_symbol(self, commodity, base):
        result = commodity.lower() + base.lower()
        if not (result in symbols):
            errmsg = 'Not supported: %s' % result
            raise PlatformNotSupportSymbolException(errmsg)

        return result

    def get_ticker(self, symbol):
        url = '/api/v2/ticker/' + symbol + "/"

        result = self._get(url)
        self._debug('ticker: \n' + json.dumps(result, indent=2))
        return result

    def get_depth(self, symbol):
        url = '/api/v2/order_book/' + symbol + "/"

        resjson = self._get(url)
        # self._debug('get_depth: \n' + json.dumps(resjson, indent=2))

        result = {}

        bids = [{'price': bid[0], 'amount': bid[1]}
                for bid in resjson['bids']]
        asks = [{'price': ask[0], 'amount': ask[1]}
                for ask in resjson['asks']]
        result = {'bids': bids, 'asks': asks}

        self._debug('order_book: \n' + json.dumps(result, indent=2))
        return result

    # NotImplementedError
    def get_account(self):
        raise NotImplementedError()

    def get_balances(self):
        url = '/api/v2/balance/'

        resjson = self._post(url)
        result = {}
        for key, value in resjson.items():
            if 'available' in key:
                result[key[:-10]] = value
        self._debug('[GET] balances: \n' + json.dumps(result, indent=2))
        return result

    def limit_buy(self, symbol, amount, price):
        url = '/api/v2/buy/' + symbol + '/'
        data = {
            'amount': amount,
            'price': price
        }

        resjson = self._post(url, data)
        result = {'id': resjson['id']}
        self._debug('[post] limit_buy: \n' + json.dumps(result, indent=2))
        return result

    def limit_sell(self, symbol, amount, price):
        url = '/api/v2/sell/' + symbol + '/'
        data = {
            'amount': amount,
            'price': price
        }

        resjson = self._post(url, data)
        result = {'id': resjson['id']}
        self._debug('[post] limit_buy: \n' + json.dumps(result, indent=2))
        return result

    def market_buy(self, symbol, amount, price):
        url = '/api/v2/buy/market/' + symbol + '/'
        data = {
            'amount': amount
        }

        resjson = self._post(url, data)
        result = {'id': resjson['id']}
        self._debug('[post] market_buy: \n' + json.dumps(result, indent=2))
        return result

    def market_sell(self, symbol, amount, price):
        url = '/api/v2/sell/market/' + symbol + '/'
        data = {
            'amount': amount
        }

        resjson = self._post(url, data)
        result = {'id': resjson['id']}
        self._debug('[post] limit_buy: \n' + json.dumps(result, indent=2))
        return result

    def get_order(self, order_id):
        url = '/api/order_status/'
        params = {
            'id': order_id,
        }

        result = self._post(url, params)
        self._debug('[POST] get_order: \n' + json.dumps(result, indent=2))
        return result

    # NotImplementedError
    def get_all_orders(self, symbol):
        raise NotImplementedError()

    def get_open_orders(self):
        url = '/api/v2/open_orders/all/'

        result = self._post(url)
        self._debug('[POST]get_open_orders: \n' + json.dumps(result, indent=2))
        return result

    def cancel_order(self, symbol, order_id):
        url = '/api/v2/cancel_order/'
        data = {
            'id': order_id,
        }

        result = self._post(url, data)
        self._debug('[POST] cancel_order: \n' + json.dumps(result, indent=2))
        return result

    def cancel_all_orders(self):
        url = '/api/cancel_all_orders/'

        result = False
        resjson = self._post(url)
        if resjson == "true":
            result = True
        self._debug('[POST] cancel_order: \n' + json.dumps(result, indent=2))
        return result

    def withdraw(self, currency, amount, address):
        url = '/api/v2/' + currency + '_withdrawal/'

        if currency == "btc" or currency == "ripple":
            url = '/api/' + currency + '_withdrawal/'

        data = {
            'amount': amount,
            'address': address
        }

        result = self._post(url, data)
        self._debug('[POST] withdraw: \n' + json.dumps(result, indent=2))
        return result
